package com.heima.wemedia.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.stream.StreamUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.heima.apis.article.IArticleClient;
import com.heima.common.dtos.ResponseResult;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.exception.CustomException;
import com.heima.model.article.dto.ArticleDto;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.wemedia.bean.ContentBean;
import com.heima.wemedia.bean.ImageCheckResult;
import com.heima.wemedia.bean.TextCheckResult;
import com.heima.wemedia.pojo.WmChannel;
import com.heima.wemedia.pojo.WmNews;
import com.heima.wemedia.service.*;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {
    @Resource
    private WmNewsService wmNewsService;
    @Resource
    private GreenService greenService;
    @Resource
    private WmChannelService wmChannelService;
    @Resource
    private WmUserService wmUserService;
    @Resource
    private IArticleClient artcileClient;

    private static final int CONTENT_TYPE_TEXT = 1;

    private static final int CONTENT_TYPE_IMAGE = 2;

    private static final String RISKLEVEL_HIGH = "high";
    private static final String RISKLEVEL_MEDIUM = "medium";
    private static final String RISKLEVEL_LOW = "low";
    private static final String RISKLEVEL_NONE = "none";

    /**
     * 自媒体文章审核
     *
     * @param id 自媒体文章id
     */
    @Override
    @Async
    public void autoScanWmNews(Integer id) {
        //1. 根据id查询文章
        WmNews wmNews = this.wmNewsService.getById(id);
        if (ObjectUtil.isEmpty(wmNews)) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //2.审核文章中文本内容
        List<String> textList = this.extractTextOrImages(wmNews, CONTENT_TYPE_TEXT);
        boolean isHandleText = this.handleTextScan(StrUtil.join("", textList), wmNews);
        if (!isHandleText) {
            //存在违规内容
            return;
        }

        //3.审核文章中图片内容
        List<String> imageList = this.extractTextOrImages(wmNews, CONTENT_TYPE_IMAGE);
        boolean isHandleImage = this.handleImageScan(imageList, wmNews);
        if (!isHandleImage) {
            //存在违规内容
            return;
        }

        //4. 更新文章状态，审核通过，调用文章微服务发布文章
        ResponseResult<Long> responseResult = this.saveAppArticle(wmNews);
        if (ObjectUtil.notEqual(responseResult.getCode(), 200)) {
            throw new CustomException(AppHttpCodeEnum.SERVER_ERROR);
        }

        wmNews.setArticleId(responseResult.getData());
        this.updateWmNews(wmNews, WmNews.Status.PUBLISHED, "审核通过");
    }


    /**
     * 保存app端相关的文章数据
     */
    private ResponseResult<Long> saveAppArticle(WmNews wmNews) {
        ArticleDto dto = BeanUtil.toBean(wmNews, ArticleDto.class);
        //文章的布局
        dto.setLayout(wmNews.getType());
        //频道
        WmChannel wmChannel = this.wmChannelService.getById(wmNews.getChannelId());
        if (ObjectUtil.isNotNull(wmChannel)) {
            dto.setChannelName(wmChannel.getName());
        }

        //作者
        dto.setAuthorId(wmNews.getUserId().longValue());
        WmUser wmUser = this.wmUserService.getById(wmNews.getUserId());
        if (ObjectUtil.isNotNull(wmUser)) {
            dto.setAuthorName(wmUser.getName());
        }

        //设置文章id
        dto.setId(wmNews.getArticleId());

        //设置创建时间
        dto.setCreatedTime(new Date());
        ResponseResult<Long> responseResult = this.artcileClient.saveArticle(dto);
        return artcileClient.saveArticle(dto);

    }


    /**
     * 审核图片内容
     */
    private boolean handleImageScan(List<String> imageList, WmNews wmNews) {
        if (ObjectUtil.isEmpty(imageList)) {
            return true;
        }
        for (String imagePath : imageList) {
            ImageCheckResult imageCheckResult = this.greenService.imageCheck(imagePath);
            //风险等级
            String riskLevel = imageCheckResult.getRiskLevel();
            //风险词
            List<String> descriptionList = imageCheckResult.getDescriptionList();
            //无风险，直接返回true
            if (ObjectUtil.equals(riskLevel, RISKLEVEL_NONE)) {
                return true;
            }

            //中等风险和低风险，交给人工审核
            if (StrUtil.equalsAny(riskLevel, RISKLEVEL_MEDIUM, RISKLEVEL_LOW) || ObjectUtil.isEmpty(riskLevel)) {
                String reason = StrUtil.format("当前文章中的图片存在不确定内容，风险等级为：{}，内容为：{}",
                        riskLevel,
                        StrUtil.join("|", descriptionList));
                updateWmNews(wmNews, WmNews.Status.ADMIN_AUTH, reason);
                return false;
            } else if (StrUtil.equals(RISKLEVEL_HIGH, riskLevel)) {
                //高风险，直接返回false
                String reason = StrUtil.format("当前文章的图片中存在违规内容，风险等级为：{}，内容为：{}",
                        riskLevel,
                        StrUtil.join("|", descriptionList));
                updateWmNews(wmNews, WmNews.Status.FAIL, reason);
                return false;
            }
        }
        return true;
    }


    /**
     * 审核纯文本内容
     */
    private boolean handleTextScan(String content, WmNews wmNews) {
        TextCheckResult textCheckResult = this.greenService.textCheck(content);
        //风险等级
        String riskLevel = textCheckResult.getRiskLevel();
        //风险词
        List<String> riskWordsList = textCheckResult.getRiskWordsList();

        //无风险，直接返回true
        if (ObjectUtil.equals(riskLevel, RISKLEVEL_NONE)) {
            return true;
        }

        //中等风险和低风险，交给人工审核
        if (StrUtil.equalsAny(riskLevel, RISKLEVEL_MEDIUM, RISKLEVEL_LOW) || StrUtil.isEmpty(riskLevel)) {
            String reason = StrUtil.format("当前文章中存在不确定内容，风险登记为：{}，风险词为：{}", riskLevel, StrUtil.join("|", riskWordsList));
            //修改文章内容
            this.updateWmNews(wmNews, WmNews.Status.ADMIN_AUTH, reason);
            return false;
        }

        //高风险，直接返回false
        String reason = StrUtil.format("当前文章中存在违规内容，风险等级为：{}，风险词为：{}", riskLevel, StrUtil.join("|", riskWordsList));
        updateWmNews(wmNews, WmNews.Status.FAIL, reason);
        return false;
    }


    /**
     * 修改文章内容
     */
    private void updateWmNews(WmNews wmNews, WmNews.Status status, String reason) {
        wmNews.setStatus(status.getCode());
        wmNews.setReason(reason);
        this.wmNewsService.updateById(wmNews);
    }


    /**
     * 从自媒体文章的内容中提取文本和图片
     *
     * @param wmNews 文章对象
     * @param type   提取的类型，1-文本 2-图片
     * @return 数据列表
     */
    private List<String> extractTextOrImages(WmNews wmNews, int type) {
        String content = wmNews.getContent();
        List<ContentBean> contentBeanList = JSONUtil.toList(content, ContentBean.class);
        List<String> list = StreamUtil.of(contentBeanList)
                .filter(contentBean -> {
                    if (ObjectUtil.equals(CONTENT_TYPE_TEXT, type)) {
                        return StrUtil.equals(contentBean.getType(), "text");
                    }
                    return StrUtil.equals(contentBean.getType(), "image");
                })
                .map(ContentBean::getValue)
                .collect(Collectors.toList());
        if (ObjectUtil.equals(CONTENT_TYPE_TEXT, type)) {
            list.add(wmNews.getTitle());
        } else if (ObjectUtil.equals(CONTENT_TYPE_IMAGE, type)) {
            //将文章的封面图片也加入进去
            list.addAll(StrUtil.split(wmNews.getImages(), ","));
        }
        return list;
    }
}

























